﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using AutoDeploy.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using LibGit2Sharp.Handlers;
using LibGit2Sharp;
using System.IO;
using AutoDeploy.ConfigModel;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace AutoDeploy.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class AutoDeployController : ControllerBase
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger<AutoDeployController> _logger;
        private readonly string[] _codeType = { "Server", "Client" };
        public AutoDeployController(IConfiguration configuration, ILogger<AutoDeployController> logger)
        {
            _configuration = configuration;
            _logger = logger;
        }

        /// <summary>
        /// 测试站点方法
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public string Index()
        {
            return "Hello AutoDeploy";
        }

        /// <summary>
        /// WebHook 回调页面
        /// </summary>
        [HttpPost]
        [TypeFilter(typeof(AuthorizationFilter))]
        public void Run(string codeType = "Server")
        {
            if (!_codeType.Contains(codeType.Trim()))
                throw new Exception("codeType parameter is illicit");

        }

        /// <summary>
        /// 拉取代码
        /// </summary>
        /// <param name="codeType">客户端还是服务端</param>
        [HttpGet]
        public void GitPull(string codeType)
        {
            var gitConfig = new Git();
            _configuration.GetSection("Git:" + codeType).Bind(gitConfig);

            // 证书
            var credentials = new CredentialsHandler((url, usernameFromUrl, types) =>
              new UsernamePasswordCredentials()
              {
                  Username = gitConfig.UserName,
                  Password = gitConfig.Password
              });

            if (!Directory.Exists(gitConfig.LocalPath))
            {
                Directory.CreateDirectory(gitConfig.LocalPath);
            }

            // 如果存在.git 文件，则拉取代码；否则clone 代码
            if (Directory.Exists(gitConfig.LocalPath + "/.git"))
            {
                using (var repository = new Repository(gitConfig.LocalPath + "/.git"))
                {

                    var result = Commands.Pull(repository, new Signature(gitConfig.UserName, gitConfig.Email, DateTimeOffset.Now)
                      , new PullOptions { FetchOptions = new FetchOptions { CredentialsProvider = credentials } });

                    _logger.LogInformation(result.Commit.Message);

                }
            }
            else
            {
                Repository.Clone(gitConfig.RepositoryUrl, gitConfig.LocalPath, new CloneOptions
                {
                    CredentialsProvider = credentials,
                    BranchName = gitConfig.Branch
                });
                _logger.LogInformation("git clone success。");
            }
        }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="codeType">客户端还是服务端</param>
        [HttpGet]
        public void Release(string codeType)
        {

            string shellName = "";
            #region 执行脚本

            // windows
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                shellName = "Windows.bat";
            // Linux
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                shellName = "Linux.sh";
            // MacOs
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                shellName = "OSX.sh";

            string shellPath = Path.Combine(Directory.GetCurrentDirectory(), "Shell", codeType, shellName);

            var processStartInfo = new ProcessStartInfo(shellPath) { RedirectStandardOutput = true, CreateNoWindow =true, UseShellExecute =false};
            var shellProcess = Process.Start(processStartInfo);
            if (shellProcess != null)
            {
                _logger.LogInformation("begin to execute shell..... ");
                using (var output = shellProcess.StandardOutput)
                {
                    _logger.LogInformation(output.ReadToEnd());
                }
                _logger.LogInformation("execute shell success....");

            }
            else
            {
                _logger.LogInformation("execute shell fail.please check if the script is written correctly");
            }
            #endregion
        }

    }
}